package cn.kivensoft.util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/** 转换类，object与各种类型之间的转换
 * @author Kiven Lee
 * @version 1.0
 * @since 2025-06-04
 */
public final class Convert {
	public static final ThreadLocal<Calendar> calThreadLocal = ThreadLocal.withInitial(Calendar::getInstance);

	private Convert() {}

	/** 转换变量为Integer类型
	 * @param value 源值
	 * @return 转换失败返回null
	 */
	public static Integer asInteger(Object value) {
		if (value == null || value.getClass() == Integer.class)
			return (Integer) value;
		if (value instanceof Number)
			return ((Number) value).intValue();
		else {
			try {
				return Integer.valueOf(value.toString());
			} catch (NumberFormatException e) {
				return null;
			}
		}
	}

	/** 转换变量为int类型
	 * @param value 原始值
	 * @param defaultValue 缺省值
	 * @return 转换失败返回defaultValue
	 */
	public static int asInt(Object value, int defaultValue) {
		Integer i = asInteger(value);
		return i == null ? defaultValue : i;
	}

	/** 转换变量为Long类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static Long asLong(Object value) {
		if (value == null || value.getClass() == Long.class)
			return (Long) value;
		if (value instanceof Number)
			return ((Number) value).longValue();
		else {
			try {
				return Long.valueOf(value.toString());
			} catch (NumberFormatException e) {
				return null;
			}
		}
	}

	/** 转换变量为long类型
	 * @param value 原始值
	 * @param defaultValue 缺省值
	 * @return 转换失败返回defaultValue
	 */
	public static long asLong(Object value, long defaultValue) {
		Long l = asLong(value);
		return l == null ? defaultValue : l;
	}

	/** 转换变量为Float类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static Float asFloat(Object value) {
		if (value == null || value.getClass() == Float.class)
			return (Float) value;
		if (value instanceof Number)
			return ((Number) value).floatValue();
		else {
			try {
				return Float.valueOf(value.toString());
			} catch (NumberFormatException e) {
				return null;
			}
		}
	}

	/** 转换变量为float类型
	 * @param value 原始值
	 * @param defaultValue 缺省值
	 * @return 转换失败返回defaultValue
	 */
	public static float asFloat(Object value, float defaultValue) {
		Float f = asFloat(value);
		return f == null ? defaultValue : f;
	}

	/** 转换变量为Double类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static Double asDouble(Object value) {
		if (value == null || value.getClass() == Double.class)
			return (Double) value;
		if (value instanceof Number)
			return ((Number) value).doubleValue();
		else {
			try {
				return Double.valueOf(value.toString());
			} catch (NumberFormatException e) {
				return null;
			}
		}
	}

	/** 转换变量为double类型
	 * @param value 原始值
	 * @param defaultValue 缺省值
	 * @return 转换失败返回defaultValue
	 */
	public static double asDouble(Object value, double defaultValue) {
		Double d = asDouble(value);
		return d == null ? defaultValue : d;
	}

	/** 转换变量为BigDecimal类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static BigDecimal asBigDecimal(Object value) {
		if (value == null || value instanceof BigDecimal)
			return (BigDecimal) value;
		else if (value instanceof Long)
			return BigDecimal.valueOf((Long) value);
		else if (value instanceof Number)
			return BigDecimal.valueOf(((Number) value).doubleValue());
		else {
			try {
				return new BigDecimal(value.toString());
			} catch (NumberFormatException e) {
				return null;
			}
		}
	}

	/** 转换变量为BigInteger类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static BigInteger asBigInteger(Object value) {
		if (value == null || value instanceof BigInteger)
			return (BigInteger) value;
		else if (value instanceof Number)
			return BigInteger.valueOf(((Number) value).longValue());
		else {
			try {
				return new BigInteger(value.toString());
			} catch (NumberFormatException e) {
				return null;
			}
		}
	}

	/** 转换变量为Boolean类型
	 * @param value 原始值
	 * @return 转换失败返回Boolean.FALSE
	 */
	public static Boolean asBoolean(Object value) {
		if (value == null || value.getClass() == Boolean.class)
			return (Boolean) value;
		else if (value instanceof Number)
			return ((Number) value).intValue() != 0;
		else
			return Boolean.valueOf(value.toString());
	}

	/** 转换变量为boolean类型
	 * @param value 原始值
	 * @param defaultValue 缺省值
	 * @return 转换失败返回defaultValue
	 */
	public static boolean asBoolean(Object value, boolean defaultValue) {
		if (value == null)
			return defaultValue;
		if (value.getClass() == Boolean.class)
			return (Boolean) value;
		if (value instanceof Number)
			return ((Number) value).intValue() != 0;

		String text = value.toString();
		if (text.equalsIgnoreCase("true"))
			return true;
		if (text.equalsIgnoreCase("false"))
			return false;

		return defaultValue;
	}

	/** 转换变量为Date类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static Date asDate(Object value) {
		if (value == null)
			return null;
		else if (value instanceof Date)
			return (Date) value;
		else if (value instanceof Number)
			return new Date(((Number) value).longValue());
		else
			return Strings.parseDate(value.toString());
	}

	/** 转换变量为LocalDateTime类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static LocalDateTime asLocalDateTime(Object value) {
		if (value == null || value.getClass() == LocalDateTime.class)
			return (LocalDateTime) value;
		else if (value.getClass() == LocalDate.class)
			return LocalDateTime.of(((LocalDate) value), LocalTime.of(0, 0));
		else
			return LocalDateTime.parse(value.toString());
	}

	/** 转换变量为LocalDate类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static LocalDate asLocalDate(Object value) {
		if (value == null || value.getClass() == LocalDate.class)
			return (LocalDate) value;
		else if (value.getClass() == LocalDateTime.class)
			return ((LocalDateTime) value).toLocalDate();
		else
			return LocalDate.parse(value.toString());
	}

	/** 转换变量为LocalTime类型
	 * @param value 原始值
	 * @return 转换失败返回null
	 */
	public static LocalTime asLocalTime(Object value) {
		if (value == null || value.getClass() == LocalTime.class)
			return (LocalTime) value;
		else if (value.getClass() == LocalDateTime.class)
			return ((LocalDateTime) value).toLocalTime();
		else
			return LocalTime.parse(value.toString());
	}

	/** 转换为Date类型
	 * @param date 输入值
	 * @return Date
	 */
	public static Date toDate(LocalDate date) {
		return Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
	}

	/** 转换为Date类型
	 * @param daettime 输入值
	 * @return Date
	 */
	public static Date toDate(LocalDateTime daettime) {
		return Date.from(daettime.atZone(ZoneId.systemDefault()).toInstant());
	}

	/** 转换为Date类型
	 * @param date 输入值
	 * @param time 输入值
	 * @return Date
	 */
	public static Date toDate(LocalDate date, LocalTime time) {
		return toDate(LocalDateTime.of(date, time));
	}

	/** 转换为Date类型
	 * @param year 年, 四位数年份
	 * @param month 月, 1-12
	 * @param day 日, 1-31表示基于月的天数
	 * @return Date
	 */
	public static Date toDate(int year, int month, int day) {
		return toDate(year, month, day, 0, 0, 0, 0);
	}

	/** 转换为Date类型
	 * @param year 年, 四位数年份
	 * @param month 月, 1-12
	 * @param day 日, 1-31
	 * @param hour 小时, 0-23
	 * @param minute 分钟,0-59
	 * @param second 秒,0-59
	 * @param millseconds 毫秒,0-999
	 * @return Date
	 */
	public static Date toDate(int year, int month, int day, int hour, int minute, int second, int millseconds) {
		Calendar cal = calThreadLocal.get();
		//noinspection MagicConstant
		cal.set(year, month - 1, day, hour, minute, second);
		cal.set(Calendar.MILLISECOND, millseconds);
		return cal.getTime();
	}

	/** 转换为LocalDate类型
	 * @param value Date
	 * @return LocalDate
	 */
	public static LocalDate toLocalDate(Date value) {
		return value.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
	}

	/** 转换为LocalTime类型
	 * @param value Date
	 * @return 只保留时间部分的LocalTime
	 */
	public static LocalTime toLocalTime(Date value) {
		return value.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
	}

	/** 转换为LocalDateTime类型
	 * @param value Date
	 * @return LocalDateTime
	 */
	public static LocalDateTime toLocalDateTime(Date value) {
		return value.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
	}

	/** 本地时间转utc时间
	 * @param value 本地时区的LocalDateTime
	 * @return 基于UTC修正后的LocalDateTime
	 */
	public static LocalDateTime localToUTC(LocalDateTime value) {
		return value.atZone(ZoneId.systemDefault())
				.withZoneSameInstant(ZoneOffset.UTC)
				.toLocalDateTime();
	}

	/** utc时间转本地时间
	 * @param value utc时区的LocalDatetime
	 * @return 基于本地时区的LocalDateTime
	 */
	public static LocalDateTime UTCToLocal(LocalDateTime value) {
		return value.atZone(ZoneOffset.UTC)
				.withZoneSameInstant(ZoneId.systemDefault())
				.toLocalDateTime();
	}

	/** 本地时间转换为GMT
	 * @param date 源日期
	 * @return 新的Date变量
	 */
	public static Date toGmt(Date date) {
		return new Date(date.getTime() - TimeZone.getDefault().getRawOffset());
	}
}
